import React, {
  useContext,
  Children,
  FunctionComponentElement,
  ReactNode,
  useState,
  MouseEvent,
  SetStateAction,
  Dispatch,
  cloneElement,
  FC,
} from 'react'
import {
  SubMenuProps,
  getSubMenuClassNames,
  DISPLAY_NAME_SUB_MENU,
} from './config'
import { MenuContext, IMenuContext } from '../../Menu'
import Icon from '../../Icon'
import { MenuItemProps, DISPLAY_NAME_MENU_ITEM } from '../MenuItem'
import Transition from '../../Transition'

const renderChildren = (children: ReactNode, parentIndex?: string) => {
  return Children.map(children, (child, index) => {
    const childElm = child as FunctionComponentElement<MenuItemProps>
    const { displayName } = childElm.type
    if (displayName === DISPLAY_NAME_MENU_ITEM) {
      const childIndex = childElm.props.index || index + ''
      return cloneElement(childElm, {
        index: parentIndex ? `${parentIndex + '-'}${childIndex}` : childIndex,
      })
      // return childElm
    } else {
      console.error(
        'Warning: Menu has a child which is not a MenuItem component'
      )
    }
  })
}

const createEventsHandler = (
  context: IMenuContext,
  subMenuOpen: boolean,
  setSubMenuOpen: Dispatch<SetStateAction<boolean>>
) => {
  const handlerSubMenuClick = (e: MouseEvent) => {
    e.preventDefault()
    setSubMenuOpen(!subMenuOpen)
  }

  let timer: any
  const handlerSubMenuMouse = (e: MouseEvent, toggle: boolean) => {
    clearTimeout(timer)
    e.preventDefault()
    timer = setTimeout(() => {
      setSubMenuOpen(toggle)
    }, 100)
  }
  const clickEvents =
    context.mode === 'vertical'
      ? {
          onClick: handlerSubMenuClick,
        }
      : {}
  const hoverEvents =
    context.mode === 'horizontal'
      ? {
          onMouseEnter: (e: MouseEvent) => {
            handlerSubMenuMouse(e, true)
          },
          onMouseLeave: (e: MouseEvent) => {
            handlerSubMenuMouse(e, false)
          },
        }
      : {}

  return {
    clickEvents,
    hoverEvents,
  }
}

export const SubMenu: FC<SubMenuProps> = props => {
  const { index, title, children } = props
  const context = useContext(MenuContext)

  const openSubMenus = context.defaultOpenSubMenus || []
  const isOpen = !!(
    index &&
    context.mode === 'vertical' &&
    openSubMenus.includes(index)
  )

  const [subMenuOpen, setSubMenuOpen] = useState(isOpen)
  const { clickEvents, hoverEvents } = createEventsHandler(
    context,
    subMenuOpen,
    setSubMenuOpen
  )

  const subMenuClasses = getSubMenuClassNames(props, () => {
    return {
      'is-active':
        context.index === index || context.index.match(new RegExp(`^${index}`)),
      'is-opened': subMenuOpen,
      'is-vertical': context.mode === 'vertical',
    }
  })
  // const subMenuUlClass = classNames('sub-menu')

  return (
    <li
      key={index}
      className={subMenuClasses}
      {...hoverEvents}
      data-testid="test-sub-menu-item">
      <div className="sub-menu-title" {...clickEvents}>
        {title}
        <Icon icon="angle-down" className="arrow-icon"></Icon>
      </div>
      <Transition in={subMenuOpen} timeout={300} animation="zoom-in-top">
        <ul className="sub-menu">{renderChildren(children, index)}</ul>
      </Transition>
    </li>
  )
}
SubMenu.displayName = DISPLAY_NAME_SUB_MENU

export default SubMenu
